# Copyright (C) 2025 Huawei Technologies Co., Ltd. All rights reserved.

<# NOTE: openUBMC NTP module Cmdlets #>

try { [NtpAddressOrigin] | Out-Null } catch {
Add-Type -TypeDefinition @'
    public enum NtpAddressOrigin {
      IPv4,
      IPv6,
      Static
    }
'@
}

try { [NtpKeyValueType] | Out-Null } catch {
Add-Type -TypeDefinition @'
    public enum NtpKeyValueType {
      Text,
      URI
    }
'@
}

function Get-openUBMCNTPSetting {
<#
.SYNOPSIS
Get openUBMC NTP Settings.

.DESCRIPTION
Get openUBMC NTP Settings.

.PARAMETER Session
openUBMC redfish session object which is created by Connect-openUBMC cmdlet.
A session object identifies an openUBMC server to which this cmdlet will be executed.

.OUTPUTS
PSObject[]
Returns PSObject indicates openUBMC NTP Settings if cmdlet executes successfully.
In case of an error or warning, exception will be returned.

.EXAMPLE

PS C:\> $credential = Get-Credential
PS C:\> $session = Connect-openUBMC -Address 192.168.1.1 -Credential $credential -TrustCert
PS C:\> Get-openUBMCNTPSetting -Session $session

Host                        : 192.168.1.1
ServiceEnabled              : True
PreferredNtpServer          : pre.openUBMC.com
AlternateNtpServer          : alt.openUBMC.com
NtpAddressOrigin            : Static
MinPollingInterval          : 10
MaxPollingInterval          : 12
ServerAuthenticationEnabled : False

.LINK
https://gitcode.com/openUBMC/cmdlets_plugin

Set-openUBMCNTPSetting
Import-openUBMCNTPKey
Connect-openUBMC
Disconnect-openUBMC

#>
  [CmdletBinding()]
  param (
    [RedfishSession[]]
    [parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, Position = 0)]
    $Session
  )

  begin {
  }

  process {
    Assert-ArrayNotNull $Session 'Session'

    $Logger.info("Invoke Get openUBMC NTP Settings function")

    $ScriptBlock = {
      param($RedfishSession)
      $(Get-Logger).info($(Trace-Session $RedfishSession "Invoke Get openUBMC NTP Settings now"))
      $Path = "/Managers/$($RedfishSession.Id)/NtpService"
      $Response = Invoke-RedfishRequest $RedfishSession $Path | ConvertFrom-WebResponse

      $Properties = @(
        "ServiceEnabled", "PreferredNtpServer", "AlternateNtpServer", "NtpAddressOrigin",
        "MinPollingInterval", "MaxPollingInterval", "ServerAuthenticationEnabled"
      )
      $Settings = Copy-ObjectProperties $Response $Properties
      return $(Update-SessionAddress $RedfishSession $Settings)
    }

    try {
      $tasks = New-Object System.Collections.ArrayList
      $pool = New-RunspacePool $Session.Count
      for ($idx = 0; $idx -lt $Session.Count; $idx++) {
        $RedfishSession = $Session[$idx]
        $Logger.info($(Trace-Session $RedfishSession "Submit Get openUBMC NTP Settings task"))
        [Void] $tasks.Add($(Start-ScriptBlockThread $pool $ScriptBlock @($RedfishSession)))
      }

      $Results = Get-AsyncTaskResults $tasks
      return ,$Results
    }
    finally {
      Close-Pool $pool
    }
  }

  end {
  }
}

function Set-openUBMCNTPSetting {
<#
.SYNOPSIS
Modify openUBMC NTP Settings.

.DESCRIPTION
Modify openUBMC NTP Settings.

.PARAMETER Session
openUBMC redfish session object which is created by Connect-openUBMC cmdlet.
A session object identifies an openUBMC server to which this cmdlet will be executed.

.PARAMETER ServiceEnabled
Indicates whether NTP is enabled.
Support values are powershell boolean value: $true(1), $false(0).

.PARAMETER PreferredNtpServer
Indicates the address of the preferred NTP server.
A character string that meets the following requirements:
- IPv4, IPv6 address or domain name
- Contains 1 to 67 characters

.PARAMETER AlternateNtpServer
Indicates the address of the alternate NTP server.
A character string that meets the following requirements:
- IPv4, IPv6 address or domain name
- Contains 1 to 67 characters

.PARAMETER NtpAddressOrigin
Indicates the NTP Address mode.
Available Value Set: IPV4, IPV6, Static

.PARAMETER MinPollingInterval
Minimum NTP polling interval.
It can be a value from 3 to 17. The value cannot be greater than MaxPollingInterval.

.PARAMETER MaxPollingInterval
Maximum NTP polling interval.
It can be a value from 3 to 17. The value cannot be less than MinPollingInterval.

.PARAMETER ServerAuthenticationEnabled
Indicates Whether server authentication is enabled.
Support values are powershell boolean value: $true(1), $false(0).

.OUTPUTS
Null
Returns Null if cmdlet executes successfully.
In case of an error or warning, exception will be returned.

.EXAMPLE

PS C:\> $credential = Get-Credential
PS C:\> $session = Connect-openUBMC -Address 192.168.1.1 -Credential $credential -TrustCert
PS C:\> Set-openUBMCNTPSetting $session -ServiceEnabled $true
          -PreferredNtpServer 'pre.openUBMC.com' -AlternateNtpServer 'alt.openUBMC.com' `
          -NtpAddressOrigin Static -ServerAuthenticationEnabled $false `
          -MinPollingInterval 10 -MaxPollingInterval 12

.LINK
https://gitcode.com/openUBMC/cmdlets_plugin

Get-openUBMCNTPSetting
Import-openUBMCNTPKey
Connect-openUBMC
Disconnect-openUBMC

#>
  [CmdletBinding()]
  param (
    [RedfishSession[]]
    [parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, Position = 0)]
    $Session,

    [Boolean[]]
    [parameter(Mandatory = $false, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)]
    $ServiceEnabled,

    [String[]]
    [ValidateLength(0, 67)]
    [parameter(Mandatory = $false, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)]
    $PreferredNtpServer,

    [String[]]
    [ValidateLength(0, 67)]
    [parameter(Mandatory = $false, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)]
    $AlternateNtpServer,

    [NtpAddressOrigin[]]
    [parameter(Mandatory = $false, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)]
    $NtpAddressOrigin,

    [int32[]]
    [ValidateRange(3, 17)]
    [parameter(Mandatory = $false, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)]
    $MinPollingInterval,

    [int32[]]
    [ValidateRange(3, 17)]
    [parameter(Mandatory = $false, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)]
    $MaxPollingInterval,

    [Boolean[]]
    [parameter(Mandatory = $false, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)]
    $ServerAuthenticationEnabled
  )

  begin {
  }

  process {
    Assert-ArrayNotNull $Session 'Session'
    $ServiceEnabledList = Get-OptionalMatchedSizeArray $Session $ServiceEnabled
    $PreferredNtpServerList = Get-OptionalMatchedSizeArray $Session $PreferredNtpServer
    $AlternateNtpServerList = Get-OptionalMatchedSizeArray $Session $AlternateNtpServer
    $NtpAddressOriginList = Get-OptionalMatchedSizeArray $Session $NtpAddressOrigin
    $MinPollingIntervalList = Get-OptionalMatchedSizeArray $Session $MinPollingInterval
    $MaxPollingIntervalList = Get-OptionalMatchedSizeArray $Session $MaxPollingInterval
    $ServerAuthenticationEnabledList = Get-OptionalMatchedSizeArray $Session $ServerAuthenticationEnabled

    $Logger.info("Invoke Set openUBMC NTP Settings function")

    $ScriptBlock = {
      param($RedfishSession, $Payload)
      $(Get-Logger).info($(Trace-Session $RedfishSession "Invoke Set openUBMC NTP Settings now"))
      $Path = "/Managers/$($RedfishSession.Id)/NtpService"
      $Logger.info($(Trace-Session $RedfishSession "Sending payload: $($Payload | ConvertTo-Json)"))
      $Response = Invoke-RedfishRequest $RedfishSession $Path 'Patch' $Payload
      Resolve-RedfishPartialSuccessResponse $RedfishSession $Response | Out-Null
      return $null
    }

    try {
      $tasks = New-Object System.Collections.ArrayList
      $pool = New-RunspacePool $Session.Count
      for ($idx = 0; $idx -lt $Session.Count; $idx++) {
        $RedfishSession = $Session[$idx]
        $Payload = @{
          ServiceEnabled=$ServiceEnabledList[$idx];
          PreferredNtpServer=$PreferredNtpServerList[$idx];
          AlternateNtpServer=$AlternateNtpServerList[$idx];
          NtpAddressOrigin=$NtpAddressOriginList[$idx];
          MinPollingInterval=$MinPollingIntervalList[$idx];
          MaxPollingInterval=$MaxPollingIntervalList[$idx];
          ServerAuthenticationEnabled=$ServerAuthenticationEnabledList[$idx];
        } | Remove-EmptyValues | Resolve-EnumValues

        if ($null -ne $Payload.MinPollingInterval -and $null -ne $Payload.MaxPollingInterval) {
          if ($Payload.MinPollingInterval -gt $Payload.MaxPollingInterval) {
            throw $(Get-i18n ERROR_NTP_MIN_GT_MAX)
          }
        }

        if ($Payload.Count -eq 0) {
          throw $(Get-i18n ERROR_NO_UPDATE_PAYLOAD)
        }

        $Parameters = @($RedfishSession, $Payload)
        $Logger.info($(Trace-Session $RedfishSession "Submit Set openUBMC NTP Settings task"))
        [Void] $tasks.Add($(Start-ScriptBlockThread $pool $ScriptBlock $Parameters))
      }

      $Results = Get-AsyncTaskResults $tasks
      return ,$Results
    }
    finally {
      Close-Pool $pool
    }
  }

  end {
  }
}

function Import-openUBMCNTPGroupKey {
<#
.SYNOPSIS
Import the openUBMC NTP group key

.DESCRIPTION
Import the openUBMC NTP group key

.PARAMETER Session
openUBMC redfish session object which is created by Connect-openUBMC cmdlet.
A session object identifies an openUBMC server to which this cmdlet will be executed.

.PARAMETER KeyFileUri
Indicates the path of NTP group key certificate file

It supports HTTPS, SFTP, NFS, SCP, and CIFS and FILE file transfer protocols.

For examples:
- local path: C:\ntp.keys or \\192.168.1.2\ntp.keys
- openUBMC local temporary path: /tmp/ntp.keys
- remote path: protocol://username:password@hostname/directory/ntp.keys


.OUTPUTS
PSObject[]
Returns the import group key task details if cmdlet executes successfully.
In case of an error or warning, exception will be returned.


.EXAMPLE

PS C:\> $credential = Get-Credential
PS C:\> $session = Connect-openUBMC -Address 192.168.1.1 -Credential $credential -TrustCert
PS C:\> Import-openUBMCNTPGroupKey -Session $session -KeyFileUri "E:\ntp.keys"

Host         : 192.168.1.1
Guid         : 4174270
ActivityName : [192.168.1.1] ntp certificate import
TaskPercent  : 100%

This example shows how to import NTP group key from local file


.EXAMPLE

PS C:\> $credential = Get-Credential
PS C:\> $session = Connect-openUBMC -Address 192.168.1.1 -Credential $credential -TrustCert
PS C:\> Import-openUBMCNTPGroupKey -Session $session -KeyFileUri "/tmp/ntp.keys"

Host         : 192.168.1.1
Id           : 1
ActivityName : [192.168.1.1] ntp certificate import
TaskPercent  : 100%

This example shows how to import NTP group key from openUBMC temp file

.EXAMPLE

PS C:\> $credential = Get-Credential
PS C:\> $session = Connect-openUBMC -Address 192.168.1.1 -Credential $credential -TrustCert
PS C:\> Import-openUBMCNTPGroupKey -Session $session -KeyFileUri "nfs://192.168.10.2/data/nfs/ntp.keys"

Host         : 192.168.1.1
Id           : 1
Name         : ntp certificate import
ActivityName : [192.168.1.1] ntp certificate import
TaskState    : Completed
StartTime    : 2018-12-21T05:51:46+00:00
EndTime      : 2018-12-21T05:51:49+00:00
TaskStatus   : OK
TaskPercent  : 100%

This example shows how to import NTP group key from NFS network file

.EXAMPLE

PS C:\> $credential = Get-Credential
PS C:\> $session = Connect-openUBMC -Address 192.168.1.1 -Credential $credential -TrustCert
PS C:\> Import-openUBMCNTPGroupKey -Session $session -KeyFileUri "sftp://192.168.1.2/data/ntp.keys" -SecureEnabled

Host         : 192.168.1.1
Id           : 1
Name         : ntp certificate import
ActivityName : [192.168.1.1] ntp certificate import
TaskState    : Completed
StartTime    : 2018-12-21T05:51:46+00:00
EndTime      : 2018-12-21T05:51:49+00:00
TaskStatus   : OK
TaskPercent  : 100%

This example shows how to import NTP group key from sftp network file with secure parameter

.LINK
https://gitcode.com/openUBMC/cmdlets_plugin

Get-openUBMCNTPSetting
Set-openUBMCNTPSetting
Connect-openUBMC
Disconnect-openUBMC

#>
  [CmdletBinding()]
  param (
    [RedfishSession[]]
    [parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, Position = 0)]
    $Session,

    [String[]]
    [parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, Position = 1)]
    $KeyFileUri,

    [switch]
    [parameter(Mandatory = $false, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)]
    $SecureEnabled
  )

  begin {
  }

  process {
    Assert-ArrayNotNull $Session 'Session'
    Assert-ArrayNotNull $KeyFileUri 'KeyFileUri'
    $KeyFileUriList = Get-MatchedSizeArray $Session $KeyFileUri 'Session' 'KeyFileUri'

    if ($SecureEnabled) {
      $SensitiveInfo = @(Get-SensitiveInfo)
      $SensitiveInfoList = Get-OptionalMatchedSizeArray $Session $SensitiveInfo
    }

    $Logger.info("Invoke Import openUBMC NTP Group Key function")

    $ScriptBlock = {
      param($RedfishSession, $KeyFileUri)

      $Logger.info($(Trace-Session $RedfishSession "Invoke Import openUBMC NTP Group Key now"))

      $StartTime = Get-Date -Format 'yyyy-MM-ddTHH:mm:sszzz'
      $KeyFilePath = Invoke-FileUploadIfNeccessary $RedfishSession $KeyFileUri $BMC.NTPKeyFileSupportSchema
      # try submit import ntp key task
      $Path = "/Managers/$($RedfishSession.Id)/NtpService/Actions/NtpService.ImportNtpKey"
      $Payload = @{
        Type= "URI";
        Content=$KeyFilePath;
      }

      $Clone = $Payload.clone()
      $Clone.Content = Protect-NetworkUriUserInfo $KeyFilePath
      $Logger.info($(Trace-Session $RedfishSession "Sending payload: $($Clone | ConvertTo-Json)"))

      $Response = Invoke-RedfishRequest $RedfishSession $Path 'POST' $Payload -ContinueEvenFailed | ConvertFrom-WebResponse
      $ExtendInfo = $Response.error.'@Message.ExtendedInfo'[0]
      if ($ExtendInfo.'@odata.id' -like '/redfish/v1/TaskService/Tasks/*') {
        return $ExtendInfo
      } else {
        $FakeTask = @{
          "Id"= "0";
          "Name"= "ntp certificate import ";
          "TaskState"= "Completed";
          "StartTime"= $StartTime;
          "EndTime"= $(Get-Date -Format 'yyyy-MM-ddTHH:mm:sszzz');
          "TaskStatus"= "OK";
          "Oem"= @{
            "openUBMC"= @{
              "TaskPercentage"= "100%";
            }
          }
        }
        if ($ExtendInfo.Severity -ne $BMC.Severity.OK.ToString()) {
          $FakeTask.TaskState = $BMC.TaskState.Exception
          $FakeTask.TaskStatus = $ExtendInfo.Severity
          $FakeTask.Oem.openUBMC.TaskPercentage = $null
          $FakeTask.Messages = $ExtendInfo
        }
        return $FakeTask
      }
    }

    try {
      $tasks = New-Object System.Collections.ArrayList
      $pool = New-RunspacePool $Session.Count
      for ($idx = 0; $idx -lt $Session.Count; $idx++) {
        $RedfishSession = $Session[$idx]
        $KeyFilePath = $KeyFileUriList[$idx]
        if ($SecureEnabled) {
          $SensitiveInfo = $SensitiveInfoList[$idx]
          $KeyFilePath = Get-CompleteUri $SensitiveInfo $KeyFilePath
        }
        $Parameters = @($RedfishSession, $KeyFilePath)
        $Logger.info($(Trace-Session $RedfishSession "Submit Import openUBMC NTP Group Key task"))
        [Void] $tasks.Add($(Start-ScriptBlockThread $pool $ScriptBlock $Parameters))
      }

      $RedfishTasks = Get-AsyncTaskResults $tasks
      $Logger.Info("Import NTP group key tasks: " + $RedfishTasks)
      return Wait-RedfishTasks $pool $Session $RedfishTasks -ShowProgress
    }
    finally {
      Close-Pool $pool
    }
  }

  end {
  }
}
